/*
Majority of code taken from AutoIT

Copyright 2006 Jonathon Bennett and the AutoIT Authors

http://www.autoitscript.com/autoit3/docs/credits.htm

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "stdafx.h"
#include "tokentypes.h"
#include "Interpreter.h"
#include "variabledomain.h"
#include "variant.h"
#include "Parser.h"
#include "errorcodes.h"

typedef int (*builtin)(token*,std::vector<token>*,Interpreter* CodeOwner);


int Builtin_ConsoleWrite(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
	if(parameters->size() != 1)
		return BUILTIN_ERR_PARAMCOUNTWRONG;


	Token_ForceStrType( &(*parameters)[0]);
	result->nValue = strlen((*parameters)[0].szValue);
	std::cout << (*parameters)[0].szValue;
	Free_Token_Attributes( &(*parameters)[0]);
	return PARSER_SUCCESS;
}


int Builtin_MsgBox(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
	if(parameters->size() < 3)
		return BUILTIN_ERR_PARAMCOUNTWRONG;

	Token_ForceInt32Type( &(*parameters)[0]);
	Token_ForceStrType( &(*parameters)[1]);
	Token_ForceStrType( &(*parameters)[2]);

	MessageBoxA(NULL,(*parameters)[2].szValue , (*parameters)[1].szValue, (*parameters)[0].nValue) ;

	for(int i=0;i<parameters->size();i++)
		Free_Token_Attributes( &(*parameters)[i]);
	return PARSER_SUCCESS;
}


int Builtin_StringLen(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
	if(parameters->size() != 1)
		return BUILTIN_ERR_PARAMCOUNTWRONG;


	Token_ForceStrType( &(*parameters)[0]);
	result->nValue = strlen((*parameters)[0].szValue);
	Free_Token_Attributes( &(*parameters)[0]);
	return PARSER_SUCCESS;
}

int Builtin_StringLeft(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
		
	if(parameters->size() != 2)
		return BUILTIN_ERR_PARAMCOUNTWRONG;

	Token_ForceStrType( &(*parameters)[0]);
	Token_ForceInt32Type( &(*parameters)[1]);

	result->type = OPT_STRINGLITERAL_TOK;
	result->szValue = new char[ (*parameters)[1].nValue + 1];
	memcpy(result->szValue, (*parameters)[0].szValue, (*parameters)[1].nValue);
	result->szValue[(*parameters)[1].nValue] = '\0';

	Free_Token_Attributes( &(*parameters)[0]);
	Free_Token_Attributes( &(*parameters)[1]);
	return PARSER_SUCCESS;
}

int Builtin_StringRight(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
		
	if(parameters->size() != 2)
		return BUILTIN_ERR_PARAMCOUNTWRONG;

	Token_ForceStrType( &(*parameters)[0]);
	Token_ForceInt32Type( &(*parameters)[1]);

	result->type = OPT_STRINGLITERAL_TOK;
	result->szValue = new char[ (*parameters)[1].nValue + 1];
	memcpy(result->szValue, &(*parameters)[0].szValue[strlen((*parameters)[0].szValue) - (*parameters)[1].nValue], (*parameters)[1].nValue);
	result->szValue[(*parameters)[1].nValue] = '\0';

	Free_Token_Attributes( &(*parameters)[0]);
	Free_Token_Attributes( &(*parameters)[1]);
	return PARSER_SUCCESS;
}

int Builtin_StringMid(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
		
	if(parameters->size() != 3)
		return BUILTIN_ERR_PARAMCOUNTWRONG;

	Token_ForceStrType( &(*parameters)[0]);
	Token_ForceInt32Type( &(*parameters)[1]);
	Token_ForceInt32Type( &(*parameters)[2]);

	result->type = OPT_STRINGLITERAL_TOK;
	result->szValue = new char[ (*parameters)[2].nValue + 1];
	memcpy(result->szValue, &(*parameters)[0].szValue[(*parameters)[1].nValue], (*parameters)[2].nValue);
	result->szValue[(*parameters)[2].nValue] = '\0';

	Free_Token_Attributes( &(*parameters)[0]);
	Free_Token_Attributes( &(*parameters)[1]);
	Free_Token_Attributes( &(*parameters)[2]);
	return PARSER_SUCCESS;
}


int Builtin_StringTrimLeft(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
		
	if(parameters->size() != 2)
		return BUILTIN_ERR_PARAMCOUNTWRONG;

	Token_ForceStrType( &(*parameters)[0]);
	Token_ForceInt32Type( &(*parameters)[1]);

	result->type = OPT_STRINGLITERAL_TOK;
	result->szValue = new char[ strlen((*parameters)[0].szValue)-(*parameters)[1].nValue + 1];
	memcpy(result->szValue, &(*parameters)[0].szValue[(*parameters)[1].nValue], strlen((*parameters)[0].szValue)-(*parameters)[1].nValue);
	result->szValue[strlen((*parameters)[0].szValue)-(*parameters)[1].nValue] = '\0';

	Free_Token_Attributes( &(*parameters)[0]);
	Free_Token_Attributes( &(*parameters)[1]);
	return PARSER_SUCCESS;
}


int Builtin_StringTrimRight(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
		
	if(parameters->size() != 2)
		return BUILTIN_ERR_PARAMCOUNTWRONG;

	Token_ForceStrType( &(*parameters)[0]);
	Token_ForceInt32Type( &(*parameters)[1]);

	result->type = OPT_STRINGLITERAL_TOK;
	result->szValue = new char[ strlen((*parameters)[0].szValue)-(*parameters)[1].nValue + 1];
	memcpy(result->szValue, (*parameters)[0].szValue, strlen((*parameters)[0].szValue)-(*parameters)[1].nValue);
	result->szValue[strlen((*parameters)[0].szValue)-(*parameters)[1].nValue] = '\0';

	Free_Token_Attributes( &(*parameters)[0]);
	Free_Token_Attributes( &(*parameters)[1]);
	return PARSER_SUCCESS;
}


int Builtin_FileOpen(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
	// $filehandle = FileOpen(<filename>, <mode>)
	// mode 0=read, mode1=append(write), 2=erase(write)
	// Returns -1 if error
	result->type = OPT_INT32_TOK;

	if(parameters->size() < 1)
		return BUILTIN_ERR_PARAMCOUNTWRONG;

	FILE	*fptr;
	int		nFreeHandle;
	int		nMode;

	Token_ForceStrType( &(*parameters)[0]);
	if(parameters->size() < 2)
		nMode = 0;
	else{
		Token_ForceInt32Type( &(*parameters)[1]);
		nMode = (*parameters)[1].nValue;
		Free_Token_Attributes( &(*parameters)[1]);
	}

	// Open a file handle in the required way
	switch ( nMode )
	{
		case 0:									// Read
			fptr = fopen((*parameters)[0].szValue, "rb");
			break;

		case 1:									// Write (append)
			fptr = fopen((*parameters)[0].szValue, "a+b");
			if (fptr)
				fseek(fptr, 0, SEEK_END);
			break;

		case 2:									// Write (erase contents)
			fptr = fopen((*parameters)[0].szValue, "w+b");
			break;

		default:
			result->nValue = -1;						// Unknown mode
			return PARSER_SUCCESS;
	}

	// Check that we have a valid file handle
	if (fptr == NULL)
	{
			result->nValue = -1;
			return PARSER_SUCCESS;
	}

	result->nValue = (int)fptr;

	Free_Token_Attributes( &(*parameters)[0]);
	return PARSER_SUCCESS;
}

int Builtin_FileClose(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
	if(parameters->size() != 1)
		return BUILTIN_ERR_PARAMCOUNTWRONG;

	Token_ForceInt32Type( &(*parameters)[0]);

	fclose((FILE*)(*parameters)[0].nValue);
	Free_Token_Attributes( &(*parameters)[0]);
	return PARSER_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////
// FileRead()
// FileRead(<filehandle | filename>, chars )
// Returns line in vResult
// @error:
// ok = 0, 1=file not open for reading, -1=eof
//
///////////////////////////////////////////////////////////////////////////////
int Builtin_FileRead(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
	if(parameters->size() != 2)
		return BUILTIN_ERR_PARAMCOUNTWRONG;

	result->type = OPT_STRINGLITERAL_TOK;

	Token_ForceInt32Type( &(*parameters)[0]);
	Token_ForceInt32Type( &(*parameters)[1]);

	char *szBuffer = new char[(*parameters)[1].nValue + 1];
	size_t Len = fread(szBuffer, 1, (*parameters)[1].nValue, (FILE*)(*parameters)[0].nValue);
	szBuffer[Len] = '\0';

	result->szValue = szBuffer;

	Free_Token_Attributes( &(*parameters)[0]);
	Free_Token_Attributes( &(*parameters)[1]);
	return PARSER_SUCCESS;
}


int Builtin_TimerInit(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
	__int64 now;

	if (!QueryPerformanceCounter((LARGE_INTEGER *)&now))
		return PARSER_SUCCESS;

	result->type = OPT_DOUBLE_TOK;
	result->fValue = (double)now;
	return PARSER_SUCCESS;
}



int Builtin_TimerDiff(token* result, std::vector<token>* parameters,Interpreter* CodeOwner)
{
	__int64 freq, now;

	if(parameters->size() != 1)
		return BUILTIN_ERR_PARAMCOUNTWRONG;

	Token_ForceDoubleType( &(*parameters)[0]);

	if (!QueryPerformanceFrequency((LARGE_INTEGER *)&freq))
		return PARSER_SUCCESS;
	if (!QueryPerformanceCounter((LARGE_INTEGER *)&now))
		return PARSER_SUCCESS;

	result->type = OPT_DOUBLE_TOK;

	result->fValue = (((double)now - (*parameters)[0].fValue) / (double)freq) * 1000.0;
	

	Free_Token_Attributes( &(*parameters)[0]);
	return PARSER_SUCCESS;
}